package com.zcgame.customview.fresh

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewConfiguration
import android.view.ViewGroup
import android.widget.OverScroller
import androidx.core.view.*
import kotlin.math.abs

/**
 *@author:huangLJ
 *@date:2021/5/10 18:07
 */
class PullRefreshLayout @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ViewGroup(context, attrs, defStyleAttr),NestedScrollingParent,NestedScrollingChild {

    companion object{
        const val TAG = "PullRefreshLayout"
        const val PULL_STATUS_INIT:Byte = 1
        const val PULL_STATUS_TOUCH_MOVE:Byte = 2
        const val PULL_STATUS_RESET:Byte = 3
        const val PULL_STATUS_REFRESHING:Byte = 4
        const val PULL_STATUS_COMPLETE:Byte = 5
        const val PULL_REFRESH_TIME = 5000L
    }
    private val mNestedScrollingChildHelper = NestedScrollingChildHelper(this)
    private val mNestedScrollingParentHeader = NestedScrollingParentHelper(this)

    private var mPullHeader:ProxyPullHeader = ProxyPullHeader(MaterialHeader(getContext()))
    private var mDownLoader:ProxyDownLoader = ProxyDownLoader(DefaultLoader())
    private var mHandlerView = mPullHeader.createHeaderView(this)
    private var mDownLoaderView :View? = null
    private var mParentScrollConsumed = IntArray(2)
    private var mParentOffsetInWindow = IntArray(2)

    private var headerScrollerHelper:ScrollerHelper
    private lateinit var loaderScrollerHelper:DownLoaderScollerHelper
    private var mPullState = PULL_STATUS_INIT//刷新状态
    private var isMoved = false //是不是在滑动
    //如果添加了loader但不想使用加载的话，设置成false
    var needLoad = true

    private var isHeader = true

    private var hasRefreshCompleteListener = false
    private var mLastY = 0f
    private var totalY = 0f
    private var topOffset = 0


    private val configuration = ViewConfiguration.get(context)
    private val touchSlop = configuration.scaledTouchSlop//最小滑动距离





    init {
        headerScrollerHelper = if(mPullHeader.needCoverContent()) OverHeaderScrollerHelper() else AllHeaderScrollerHelper()
        setWillNotDraw(false)
        addHeaderView()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

        for(i in 0 until childCount){
            val child = getChildAt(i)
            if(child.visibility != View.GONE){
                measureChild(child,widthMeasureSpec,heightMeasureSpec)
            }
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        val contentView = getChildView()
        val headerAlreadyOffset = headerScrollerHelper.getAlreadyOffset()
        val headerViewLayoutOffset = mPullHeader.getConfig().headerViewLayoutOffset(this, mHandlerView)
        var childLeft = paddingLeft
        var childTop = - headerViewLayoutOffset - headerAlreadyOffset
        mHandlerView.layout(childLeft,childTop,mHandlerView.measuredWidth+childLeft,childTop + mHandlerView.measuredHeight)
        topOffset =  - mHandlerView.measuredWidth
        childLeft = paddingLeft
        childTop = paddingTop
        contentView?.layout(childLeft,childTop,contentView.measuredWidth,contentView.measuredHeight)
        if(mDownLoaderView!=null){
            val footLoaderOffset = loaderScrollerHelper.getAlreadyOffset()
            childLeft = paddingLeft
            childTop = measuredHeight + paddingTop - headerAlreadyOffset
            mDownLoaderView!!.layout(childLeft,childTop,childLeft+mDownLoaderView!!.measuredWidth,childTop+mDownLoaderView!!.measuredHeight)
        }

    }
    /*-------------------------------外部调用的方法 -- start -------------------------------------*/
    //添加加载尾部
    fun setFootView(downLoader:DownLoader){
        if(!::loaderScrollerHelper.isInitialized){
            loaderScrollerHelper = DownLoaderScollerHelper()
        }
        if(!loaderScrollerHelper.isFinished()){
            //停止动画并到达指定地点
            loaderScrollerHelper.abortAnimation()
        }
        if (mDownLoaderView!= null){
            removeView(mDownLoaderView)
        }

        mDownLoader.setFootView(downLoader)
        mDownLoaderView = mDownLoader.createLoaderView(this)
        var layoutParams = mHandlerView.layoutParams
        if (layoutParams == null) {
            layoutParams = LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT)
        }
        addView(mDownLoaderView,layoutParams)

    }
    //给刷新事件注册监听
    fun  addPullListener(listener:OnPullListener){
        mPullHeader.addHeaderListener(listener)
    }
    //解除注册
    fun removePullListener(listener:OnPullListener){
        mPullHeader.removeHeaderListener(listener)
    }
    //添加刷新的头部
    fun setHeadView(pullHeader:PullHeader){
        setHeadView(pullHeader,true)
    }
    fun setHeadView(pullHeader: PullHeader,isPinContent:Boolean){
        if(!headerScrollerHelper.isFinished()){
            headerScrollerHelper.abortAnimation()
        }
        headerScrollerHelper = if(isPinContent){
            OverHeaderScrollerHelper()
        }else{
            AllHeaderScrollerHelper()
        }

        mPullHeader.setPullHandler(pullHeader)
        removeView(mHandlerView)
        addHeaderView()
    }

    fun refreshComplete(){
        if(width == 0){
            post {
                finishHeader()
            }
        }else{
            finishHeader()
        }
        hasRefreshCompleteListener = true
    }

    /*--------------------------------外部调用方法 -- end ------------------------------------*/



    /**---------------------------NestedScrollingParent -- start ---------------------------*/
    /**
     * onStartNestedScroll返回true之后调用
     */
    override fun onNestedScrollAccepted(child: View, target: View, axes: Int) {
        mNestedScrollingParentHeader.onNestedScrollAccepted(child, target, axes)
    }

    /**
     * 子控件开始滑动的时候调用
     * return 是否支持嵌套
     */
    override fun onStartNestedScroll(child: View, target: View, axes: Int): Boolean {
        return isEnabled && mPullState != PULL_STATUS_REFRESHING && (axes and ViewCompat.SCROLL_AXIS_VERTICAL) != 0
    }


    override fun onNestedFling(target: View, velocityX: Float, velocityY: Float, consumed: Boolean): Boolean {
        return dispatchNestedFling(velocityX,velocityY,consumed)
    }

    override fun getNestedScrollAxes(): Int {
        return mNestedScrollingParentHeader.nestedScrollAxes
    }

    /**
     * 滑动时分为2个流程，准备滑动，和滑动
     *dy:手势向下滑动的时候为负值
     * 开始滑动时调用
     */
    /**
     * 防止滑动过量
     */
    override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray) {
        //允许滑动过程中回退
        if (dy > 0 && isHeader) {
            val offsetY = headerScrollerHelper.getOffsetY()
            if(offsetY > 0){
                return
            }
            val absOffsetY = abs(offsetY)
            //防止滑动过量
            if(dy > absOffsetY){
                consumed[1] = absOffsetY
            }else{
                consumed[1] = dy
            }
            touchMoveUp(consumed[1])

        }else if(dy < 0  && !isHeader){
            val offsetY = loaderScrollerHelper.getOffsetY()
            if(offsetY < 0) return
            if(-dy > offsetY){
                consumed[1] = offsetY
            }else{
                consumed[1] = dy
            }
            touchMoveDown(dy.toFloat())
        }
        val parentConsumed:IntArray = mParentScrollConsumed
        if(dispatchNestedPreScroll(dx -consumed[0],dy - consumed[1],mParentScrollConsumed,null)){
            consumed[0] += parentConsumed[0]
            consumed[1] += parentConsumed[1]
        }
    }

    /**
     * 滑动后调用
     */
    override fun onNestedScroll(target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int) {
        dispatchNestedScroll(dxConsumed,dyConsumed,dxUnconsumed,dyUnconsumed,mParentOffsetInWindow)
        val dy = dyUnconsumed+mParentOffsetInWindow[1]
        if(dy < 0 && !canChildScrollUp()){
            touchMoveUp(dy)
        }else if (dy >0 && !canChildScrollDown()){
            touchMoveDown(dy.toFloat())
        }
    }

    override fun onNestedPreFling(target: View, velocityX: Float, velocityY: Float): Boolean {
        return dispatchNestedPreFling(velocityX,velocityY)
    }

    override fun onStopNestedScroll(target: View) {
        if(isHeader)finishUpSpinner()else finishDownSpinner()
        stopNestedScroll()
    }

    /**---------------------------NestedScrollingParent -- end ---------------------------*/


    /**
     *作为子类不做过多处理
     */
    /**---------------------------NestedScrollingChild -- start ---------------------------*/
    /**
     * 从子类上接收，onNestedScroll---> 后传递到这
     */
    override fun dispatchNestedScroll(dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, offsetInWindow: IntArray?): Boolean {
        return mNestedScrollingChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow)
    }

    override fun isNestedScrollingEnabled(): Boolean {
        return mNestedScrollingChildHelper.isNestedScrollingEnabled
    }

    override fun dispatchNestedPreScroll(dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?): Boolean {
        return mNestedScrollingChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)
    }

    override fun stopNestedScroll() {
        return mNestedScrollingChildHelper.stopNestedScroll()
    }

    override fun hasNestedScrollingParent(): Boolean {
        return mNestedScrollingChildHelper.hasNestedScrollingParent()
    }

    override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float): Boolean {
        return mNestedScrollingChildHelper.dispatchNestedPreFling(velocityX, velocityY)
    }

    override fun setNestedScrollingEnabled(enabled: Boolean) {
        mNestedScrollingChildHelper.isNestedScrollingEnabled = enabled
    }

    override fun dispatchNestedFling(velocityX: Float, velocityY: Float, consumed: Boolean): Boolean {
        return mNestedScrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed)
    }

    override fun startNestedScroll(axes: Int): Boolean {
        return mNestedScrollingChildHelper.startNestedScroll(axes)
    }

    override fun computeScroll() {
        super.computeScroll()
        postInvalidate()
        if(isHeader){
            headerScrollerHelper.computeScroll()
        }else{
            loaderScrollerHelper.computeScroll()
        }
    }

    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {

        return super.dispatchTouchEvent(ev)
    }

    override fun onOverScrolled(scrollX: Int, scrollY: Int, clampedX: Boolean, clampedY: Boolean) {
        super.scrollTo(scrollX,scrollY)
    }

    /**---------------------------NestedScrollingChild -- end ---------------------------*/





    private fun addHeaderView() {
        mHandlerView = mPullHeader.createHeaderView(this)
        var layoutParams = mHandlerView.layoutParams
        if (layoutParams == null) {
            layoutParams = LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT)
        }
        addView(mHandlerView,layoutParams)
    }



    override fun onTouchEvent(event: MotionEvent?): Boolean {
        if(mPullState == PULL_STATUS_REFRESHING){
            return true
        }

        //如果不可见 || 子view能滑动
        if(!isEnabled) return false
        when(event?.action){
            MotionEvent.ACTION_DOWN ->{
                isMoved = false
                if(!headerScrollerHelper.isFinished()){
                    headerScrollerHelper.abortAnimation()
                }
                //记录点击后的坐标
                mLastY = event.y
            }
            MotionEvent.ACTION_MOVE->{
                val deltaY = mLastY - event.y
                totalY+=deltaY

                if(!isMoved && abs(deltaY) > touchSlop){
                    isMoved = true
                }
                //向上滑动拦截
                if(!canChildScrollUp()&&isMoved){
                    if(totalY <= 0){
                        touchMoveUp((deltaY).toInt())
                        mLastY = event.y
                    }else{
                        isMoved = false
                        return super.onInterceptTouchEvent(event)
                    }
                }else if(!canChildScrollDown()&&isMoved&&::loaderScrollerHelper.isInitialized){
                    if(totalY>=0){
                        touchMoveDown(deltaY)
                        mLastY = event.y
                    }else{
                        isMoved = false
                        return super.onInterceptTouchEvent(event)
                    }
                }
                return super.onInterceptTouchEvent(event)
            }
            MotionEvent.ACTION_UP ->{
                if(isMoved){
                    totalY = 0f
                    isMoved = false
                    if(isHeader) finishUpSpinner()else finishDownSpinner()
                }
                return false
            }
            else ->{
                return super.onTouchEvent(event)
            }
        }
        return true
    }

    private fun touchMoveDown(deltaY: Float) {
        if(::loaderScrollerHelper.isInitialized) return
        if(!loaderScrollerHelper.isFinished()){
            loaderScrollerHelper.abortAnimation()
        }
        val offsetX = loaderScrollerHelper.getOffsetX()
        val offsetY = loaderScrollerHelper.getOffsetY()
        val totalDistance = mDownLoader.getConfig().totalDistance(this, mDownLoaderView!!)
        if(offsetY - deltaY < totalDistance){
            if (mPullState != PULL_STATUS_TOUCH_MOVE) {
                mPullState = PULL_STATUS_TOUCH_MOVE
                mDownLoader.onDownBegin(this)
            }
        }
        val dys = mDownLoader.getConfig().dispatchTouchMove(this,deltaY,-offsetY,totalDistance)
        loaderScrollerHelper.overScrollByCompat(0,dys,offsetX,offsetY,0,0,0,totalDistance)
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {

        if(mPullState == PULL_STATUS_REFRESHING){
            return true
        }
        //如果不可见 || 子view能滑动
        if(!isEnabled) return false

        when(ev?.action){
            MotionEvent.ACTION_DOWN->{
                isMoved = false
                mLastY = ev.y
            }
            /**
             * 判断滑动距离是不是达到了移动标准,如果达到了就拦截
             */
            MotionEvent.ACTION_MOVE->{
                val deltaY = mLastY - ev.y
                totalY+=deltaY

                if(!isMoved && abs(deltaY) > touchSlop){
                    isMoved = true
                }

                //向上滑动拦截
                if(!canChildScrollUp()&&isMoved){
                    if(totalY <= 0){
                        touchMoveUp((deltaY).toInt())
                        mLastY = ev.y
                    }else{
                        isMoved = false
                        return super.onInterceptTouchEvent(ev)
                    }
                }else if(!canChildScrollDown()&&isMoved&&::loaderScrollerHelper.isInitialized){

                    if(totalY>=0){
                        touchMoveDown(deltaY)

                        mLastY = ev.y
                    }else{
                        isMoved = false
                        return super.onInterceptTouchEvent(ev)
                    }
                }
                return super.onInterceptTouchEvent(ev)
            }
            MotionEvent.ACTION_UP->{
                isMoved = false
                if(isHeader) finishUpSpinner() else finishDownSpinner()
            }
            else ->{
                return super.onInterceptTouchEvent(ev)
            }
        }
        return isMoved
    }

    private fun finishDownSpinner() {
        val offsetToRefresh = mDownLoader.getConfig().offsetToLoader(this,mDownLoaderView!!)
        val offsetY = loaderScrollerHelper.getOffsetY()

        if(offsetY > offsetToRefresh){
            setFootLoader()
            postDelayed({finishFoot()},PULL_REFRESH_TIME)
        }else{
            reset(false)
        }
    }

    private fun setFootLoader() {
        mPullState = PULL_STATUS_REFRESHING
        mDownLoader.onLoading(this)
        val offsetToLoader = mDownLoader.getConfig().offsetToKeepLoader(this, mDownLoaderView!!)
        val dy = offsetToLoader - loaderScrollerHelper.getOffsetY()
        loaderScrollerHelper.startScroll(loaderScrollerHelper.getOffsetX(),loaderScrollerHelper.getOffsetY()
                ,loaderScrollerHelper.getOffsetX(),dy)
    }

    private fun finishUpSpinner() {
        val offsetToRefresh = mPullHeader.getConfig().offsetToRefresh(this, mHandlerView)
        val offsetY = headerScrollerHelper.getOffsetY()

        if(-offsetY > offsetToRefresh){
            setRefresh()
            //如果没有主动关闭的话，我就自己5秒后关闭了
            postDelayed({
                finishHeader()
            }, PULL_REFRESH_TIME)
        }else{
            reset(true)
        }
    }

    private fun reset(pullRelease:Boolean) {
        mPullState = PULL_STATUS_RESET
        if(pullRelease){
            mPullHeader.onReset(this,pullRelease)
            val dy = -headerScrollerHelper.getOffsetY()
            headerScrollerHelper.startScroll(headerScrollerHelper.getOffsetX(),headerScrollerHelper.getOffsetY(),0,dy)
        }else{
            mDownLoader.onReset(this,pullRelease)
            val dy = -loaderScrollerHelper.getOffsetY()
            loaderScrollerHelper.startScroll(loaderScrollerHelper.getOffsetX(),loaderScrollerHelper.getOffsetY(),0,dy)
        }
    }

    private fun finishHeader() {
        mPullState = PULL_STATUS_COMPLETE
        mPullHeader.onPullRefreshFinish(this)
        headerScrollerHelper.startScroll(headerScrollerHelper.getOffsetX(),headerScrollerHelper.getOffsetY(),0,-headerScrollerHelper.getOffsetY())
    }

    private fun finishFoot(){
        mPullState = PULL_STATUS_COMPLETE
        mDownLoader.onPullLoadedFinish(this)
        loaderScrollerHelper.startScroll(loaderScrollerHelper.getOffsetX(),loaderScrollerHelper.getOffsetY(),0,-loaderScrollerHelper.getOffsetY())
    }

    private fun setRefresh() {
        mPullState = PULL_STATUS_REFRESHING
        mPullHeader.onRefreshing(this)
        val keepHeaderWhile = mPullHeader.getConfig().offsetToKeepHeaderWhileLoading(this, mHandlerView)
        val dy = -keepHeaderWhile - headerScrollerHelper.getOffsetY()
        headerScrollerHelper.startScroll(headerScrollerHelper.getOffsetX(),headerScrollerHelper.getOffsetY(),headerScrollerHelper.getOffsetX(),dy)
    }

    private fun touchMoveUp(dy: Int) {
        if(!headerScrollerHelper.isFinished()){
            headerScrollerHelper.abortAnimation()
        }
        val offsetX = headerScrollerHelper.getOffsetX()
        val offsetY = headerScrollerHelper.getOffsetY()
        val totalDistance = mPullHeader.getConfig().totalDistance(this, mHandlerView)
        //当还没到达目标值的时候，就不执行刷新
        if(-offsetY - dy < totalDistance){
            if(mPullState != PULL_STATUS_TOUCH_MOVE){
                mPullState = PULL_STATUS_TOUCH_MOVE
                mPullHeader.onPullBegin(this)
            }

            val dys = (mPullHeader.getConfig().dispatchTouchMove(this, dy, -offsetY, totalDistance)).toFloat()
            headerScrollerHelper.overScrollByCompat(0, dys.toInt(),offsetX,offsetY,0,0,0,totalDistance)
        }
    }

    /**
     * 子view是不是能向上滑动
     */
    private fun canChildScrollUp(): Boolean {
        getChildView()?:return false
        return mPullHeader.getConfig().contentCanScrollUp(this,getChildView()!!)
    }

    private fun canChildScrollDown():Boolean{
        getChildView()?:return false
        return mDownLoader.getConfig().contentCanScrollDown(this,getChildView()!!)
    }

    /**
     * 获取中间显示内容的View,可能为空
     */
    private fun getChildView(): View? {
    var a = 0
        for(i in 0 until childCount){
            val child = getChildAt(i)
            if(child != mHandlerView && child != mDownLoaderView){
                a++
                return child
            }
        }
        if(a != 1){
             throw IllegalArgumentException("PullRefreshLayout must be one child")
        }
        return getChildAt(childCount-1)
    }


    abstract inner class ScrollerHelper{
        protected val mScroller = OverScroller(context)

        abstract fun  getOffsetX():Int

        abstract fun getOffsetY():Int

        abstract fun abortAnimation()

        open fun computeScroll(){}

        abstract fun startScroll(startX: Int, startY: Int, dx: Int, dy: Int)

        abstract fun overScrollByCompat(deltaX: Int, deltaY: Int, scrollX: Int, scrollY: Int, scrollRangeX: Int, scrollRangeY: Int, maxOverScrollX: Int, maxOverScrollY: Int)

        fun isFinished() = mScroller.isFinished

        open fun getAlreadyOffset():Int{
            return 0;
        }
    }

    inner class OverHeaderScrollerHelper: ScrollerHelper(){

        private val runnable = object :Runnable{
            override fun run() {
                if (mScroller.computeScrollOffset()) {
                    val currX = mScroller.currX
                    val currY = mScroller.currY
                    val scrollX = getOffsetX()
                    val scrollY = getOffsetY()
                    overScrollByCompat(currX-scrollX,currY-scrollY,scrollX,scrollY,
                    0,0,0,mHandlerView.measuredHeight)
                    if (!mScroller.isFinished && mScroller.finalY != mScroller.currY) {
                        post(this)
                    }
                }
            }

        }
        override fun getOffsetX(): Int {
            return mHandlerView.left
        }

        override fun getOffsetY(): Int {
            return -mHandlerView.bottom
        }

        override fun abortAnimation(){
            mScroller.abortAnimation()
            removeCallbacks(runnable)
        }



        override fun startScroll(startX: Int, startY: Int, dx: Int, dy: Int) {
            removeCallbacks(runnable)
            mScroller.startScroll(startX, startY, dx, dy,8000)
            post(runnable)
        }

        override fun getAlreadyOffset(): Int {
            return -mHandlerView.bottom
        }

        override fun overScrollByCompat(deltaX: Int, deltaY: Int, scrollX: Int, scrollY: Int, scrollRangeX: Int, scrollRangeY: Int, maxOverScrollX: Int, maxOverScrollY: Int) {
            var newScrollX = scrollX
            newScrollX += deltaX

            var newScrollY = scrollY
            newScrollY += deltaY

            val left = -maxOverScrollX
            val right = maxOverScrollX + scrollRangeX
            val top = -maxOverScrollY
            val bottom = maxOverScrollY + scrollRangeY
            // 限制滑动的最大宽高
            if(newScrollX > right){
                newScrollX = right
            }else if (newScrollX < left){
                newScrollX = left
            }

            if(newScrollY < top){
                newScrollY = top
            }else if (newScrollY > bottom){
                newScrollY = bottom
            }
            if(newScrollY > 0){
                newScrollY = 0
            }
            val currentDistance = -newScrollY
            //如果不只有刷新头一个页面的话
            if (indexOfChild(mHandlerView) != childCount -1) {
                //把mHandlerView放在最上层
                bringChildToFront(mHandlerView)
            }
            if(deltaY != 0){
                //移动子view的关键代码
                ViewCompat.offsetTopAndBottom(mHandlerView,-deltaY)
                mPullHeader.onPositionChange(this@PullRefreshLayout,mPullState,deltaY,currentDistance)
            }
        }

    }
    inner class AllHeaderScrollerHelper:ScrollerHelper(){
        override fun getOffsetX(): Int {
            return scrollX
        }

        override fun getOffsetY(): Int {
            //返回2个view坐标点的距离
            return scrollY
        }

        override fun abortAnimation() {
            mScroller.abortAnimation()
        }
        override fun computeScroll() {
            //如果滚动还没有完成的话
            if (mScroller.computeScrollOffset()) {
                overScrollByCompat(mScroller.currX - getOffsetX(),mScroller.currY-getOffsetY(),
                        getOffsetX(),getOffsetY(),0,0,0,mHandlerView.measuredHeight*3)
            }
        }

        override fun startScroll(startX: Int, startY: Int, dx: Int, dy: Int) {
            mScroller.startScroll(startX, startY, dx, dy,800)
            ViewCompat.postInvalidateOnAnimation(this@PullRefreshLayout)
        }

        override fun overScrollByCompat(deltaX: Int, deltaY: Int, scrollX: Int, scrollY: Int, scrollRangeX: Int, scrollRangeY: Int, maxOverScrollX: Int, maxOverScrollY: Int) {
            var newScrollX = scrollX
            var newScrollY = scrollY
            newScrollX += deltaX
            newScrollY += deltaY


            val left = -maxOverScrollX
            val right = maxOverScrollX+scrollRangeX
            val top = maxOverScrollY //能够到达的最高点的top值
            val bottom = -maxOverScrollY+scrollRangeY // 能够到达的最低点的bottom值


            var clampedX = false//是不是超标了
            if(newScrollX > right){
                newScrollX = right
                clampedX = true
            }else if (newScrollX < left){
                newScrollX = left
                clampedX = true
            }
            var clampedY = false
            if(newScrollY < bottom){
                newScrollY = bottom
                clampedY = true
            }else if(newScrollY > top){
                newScrollY = top
                clampedY = true
            }
            //不允许回弹
            if(newScrollY > 0){
                newScrollY = 0
            }

            val deltaYs = newScrollY - getOffsetY()

            val currentDistance = -newScrollY

            if(deltaYs != 0){
                isHeader = true
                scrollTo(newScrollX,newScrollY)
                mPullHeader.onPositionChange(this@PullRefreshLayout,mPullState,deltaYs,currentDistance)
            }
            if(!mScroller.isFinished && mScroller.finalY != mScroller.currY){
                ViewCompat.postInvalidateOnAnimation(this@PullRefreshLayout)
            }
        }
    }
    inner class DownLoaderScollerHelper: ScrollerHelper(){
        override fun getOffsetX(): Int {
            return scrollX
        }

        override fun getOffsetY(): Int {
            return scrollY
        }

        override fun abortAnimation() {
            mScroller.abortAnimation()
        }

        override fun computeScroll() {
            //如果滚动还没有完成的话
            if (mScroller.computeScrollOffset()) {

                overScrollByCompat(mScroller.currX - getOffsetX(),mScroller.currY-getOffsetY(),
                        getOffsetX(),getOffsetY(),0,0,0,mDownLoaderView!!.measuredHeight*3)
            }
        }

        override fun startScroll(startX: Int, startY: Int, dx: Int, dy: Int) {
            mScroller.startScroll(startX, startY, dx, dy,800)

            ViewCompat.postInvalidateOnAnimation(this@PullRefreshLayout)
        }

        override fun overScrollByCompat(deltaX: Int, deltaY: Int, scrollX: Int, scrollY: Int, scrollRangeX: Int, scrollRangeY: Int, maxOverScrollX: Int, maxOverScrollY: Int) {

            var newScrollY = scrollY
            var newScrollX = scrollX
            newScrollX += deltaX
            newScrollY += deltaY
            val top = -maxOverScrollY //能够到达的最高点的top值
            val bottom = maxOverScrollY// 能够向下滑动的最高点距离
            val left = -maxOverScrollX
            val right = maxOverScrollX

            var clampedY = false
            var clampedX = false//是不是超标了
            if(newScrollX > right){
                newScrollX = right
                clampedX = true
            }else if (newScrollX < left) {
                newScrollX = left
                clampedX = true
            }
            if(newScrollY > bottom){
                newScrollY = bottom
                clampedY = true
            }else if(newScrollY < top){
               newScrollY = top
                clampedY = true
            }
            if(newScrollY < 0){
                newScrollY = 0
            }
            val deltaYs = newScrollY - getOffsetY()
            val currentDistance = -newScrollY

            if(deltaYs != 0){
                isHeader = false
                scrollTo(newScrollX,newScrollY)
                mDownLoader.onPositionChange(this@PullRefreshLayout,mPullState,deltaYs,currentDistance)
            }
        }
    }
}